package org.colafries.admin.service.impl.index;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.colafries.admin.entity.domain.index.DataDomain;
import org.colafries.admin.entity.domain.index.LogicDimRelation;
import org.colafries.admin.entity.domain.index.LogicDimension;
import org.colafries.admin.entity.vo.index.LogicDimensionReqVO;
import org.colafries.admin.exceptions.ServiceException;
import org.colafries.admin.exceptions.enums.ErrorCodeEnum;
import org.colafries.admin.mapper.index.LogicDimensionMapper;
import org.colafries.admin.service.impl.IBaseServiceImpl;
import org.colafries.admin.service.index.IDataDomainService;
import org.colafries.admin.service.index.ILogicDimRelationService;
import org.colafries.admin.service.index.ILogicDimensionService;
import org.colafries.common.constants.Constants;
import org.colafries.common.snowflake.SnowFlake;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 逻辑维度 服务实现类
 * </p>
 *
 * @author Ann
 * @since 2024-06-03
 */
@Service("ILogicDimensionServiceImpl")
public class ILogicDimensionServiceImpl extends IBaseServiceImpl<LogicDimensionMapper, LogicDimension, LogicDimensionReqVO>
        implements ILogicDimensionService {
    @Resource
    IDataDomainService iDataDomainService;
    @Resource
    ILogicDimRelationService iLogicDimRelationService;

    @Override
    public int add(LogicDimensionReqVO reqVO) {
        validateReqVO(reqVO);
        //同名验证
        int cnt = baseMapper.selectCount(Wrappers.<LogicDimension>lambdaQuery().eq(LogicDimension::getField, reqVO.getField()));
        if (cnt > 0) {
            log.warn("新增逻辑维度失败，英文名重复");
            throw new ServiceException(ErrorCodeEnum.GL999999, "新增逻辑维度失败，英文名重复");
        }
        LogicDimension logicDimension = LogicDimension.builder()
                .code(SnowFlake.nextId())
                .version(Constants.VERSION_FIRST)
                .dataDomainCode(reqVO.getDataDomainCode())
                .dimType(reqVO.getDimType())
                .field(reqVO.getField())
                .alias(reqVO.getAlias())
                .description(reqVO.getDescription())
                .createUser(reqVO.getCreateUser())
                .updateUser(reqVO.getUpdateUser())
                .build();

        return baseMapper.insert(logicDimension);
    }

    @Override
    public int update(LogicDimensionReqVO reqVO) {
        validateReqVO(reqVO);
        Long logicDimensionCode = reqVO.getCode();
        LogicDimension oldLogicDimension = queryByCode(logicDimensionCode);
        if (oldLogicDimension == null) {
            log.warn("修改逻辑维度失败，逻辑维度不存在 code:" + logicDimensionCode);
            throw new ServiceException(ErrorCodeEnum.GL999999, "修改逻辑维度失败，逻辑维度不存在 code:" + logicDimensionCode);
        }
        LogicDimension newLogicDimension = LogicDimension.builder()
                .id(oldLogicDimension.getId())
                .code(oldLogicDimension.getCode())
                .version(oldLogicDimension.getVersion() + 1)
                .dataDomainCode(reqVO.getDataDomainCode())
                .dimType(reqVO.getDimType())
                .field(reqVO.getField())
                .alias(reqVO.getAlias())
                .description(reqVO.getDescription())
                .updateUser(reqVO.getUpdateUser())
                .build();
        return baseMapper.updateById(newLogicDimension);
    }

    @Override
    public int delete(LogicDimensionReqVO reqVO) {
        Long logicDimensionCode = reqVO.getCode();
        LogicDimension logicDimension = queryByCode(logicDimensionCode);
        if (logicDimension == null) {
            log.warn("删除逻辑维度失败，逻辑维度不存在 code:" + logicDimensionCode);
            throw new ServiceException(ErrorCodeEnum.GL999999, "删除逻辑维度失败，逻辑维度不存在 code:" + logicDimensionCode);
        }
        return baseMapper.deleteById(logicDimension.getId());
    }

    @Override
    public List<LogicDimension> listAll(LogicDimensionReqVO reqVO) {
        LambdaQueryWrapper<LogicDimension> queryWrapper = new LambdaQueryWrapper<>();
        List<LogicDimension> dimensions = baseMapper.selectList(queryWrapper);
        return dimensions.stream()
                .peek(dimension -> {
                    List<LogicDimRelation> dimRelations = iLogicDimRelationService.listByDimensionCode(dimension.getCode());
                    if (CollectionUtils.isEmpty(dimensions)) {
                        dimension.setLogicTableCodes(Collections.emptyList());
                        log.warn("维度与逻辑事实表关系不存在 维度code:" + dimension.getCode());
                    }
                    List<Long> tableCodeList = dimRelations.stream().map(LogicDimRelation::getLogicTableCode).collect(Collectors.toList());
                    dimension.setLogicTableCodes(tableCodeList);
                })
                .filter(dimension-> {
                    if (reqVO.getLogicTableCode() == null){
                        return true;
                    }
                    return dimension.getLogicTableCodes().contains(reqVO.getLogicTableCode());
                })
                .collect(Collectors.toList());
    }

    @Override
    public IPage<LogicDimension> pageList(LogicDimensionReqVO reqVO) {
        return super.pageList(reqVO);
    }

    /**
     * 根据code查询逻辑维度
     *
     * @param logicDimensionCode
     * @return org.colafries.admin.entity.domain.index.LogicDimension
     * @Author anning
     * @Date 2024/6/14
     */
    @Override
    public LogicDimension queryByCode(Long logicDimensionCode) {
        return baseMapper.selectOne(
                Wrappers.<LogicDimension>lambdaQuery().eq(LogicDimension::getCode, logicDimensionCode)
        );
    }

    /**
     * 请求参数验证
     *
     * @param reqVO
     * @return void
     * @Author anning
     * @Date 2024/6/14
     */
    private void validateReqVO(LogicDimensionReqVO reqVO) {
        // 数据领域code检查
        Long dataDomainCode = reqVO.getDataDomainCode();
        if (dataDomainCode == null || dataDomainCode == 0L) {
            log.warn("数据领域code值非法 code:" + dataDomainCode);
            throw new ServiceException(ErrorCodeEnum.GL999999, "数据领域code值非法 code:" + dataDomainCode);
        }
        // 维度英文名检查
        if (StringUtils.isEmpty(reqVO.getField())) {
            log.warn("维度英文名不能为空");
            throw new ServiceException(ErrorCodeEnum.GL999999, "维度英文名不能为空");
        }
        if (StringUtils.length(reqVO.getField()) > 50) {
            log.warn("维度英文名长度不能超过50");
            throw new ServiceException(ErrorCodeEnum.GL999999, "维度英文名长度不能超过50");
        }
        // 维度英文名检查
        if (StringUtils.isEmpty(reqVO.getAlias())) {
            log.warn("维度名称不能为空");
            throw new ServiceException(ErrorCodeEnum.GL999999, "维度名称不能为空");
        }
        if (StringUtils.length(reqVO.getAlias()) > 100) {
            log.warn("维度名称长度不能超过100");
            throw new ServiceException(ErrorCodeEnum.GL999999, "维度名称长度不能超过100");
        }
        // 维度描述检查
        if (StringUtils.isEmpty(reqVO.getAlias())) {
            log.warn("维度描述不能为空");
            throw new ServiceException(ErrorCodeEnum.GL999999, "维度描述不能为空");
        }
        if (StringUtils.length(reqVO.getAlias()) > 255) {
            log.warn("维度描述长度不能超过255");
            throw new ServiceException(ErrorCodeEnum.GL999999, "维度描述长度不能超过255");
        }
        // 数据领域exists验证
        DataDomain dataDomain = iDataDomainService.queryByCode(dataDomainCode);
        if (dataDomain == null) {
            log.warn("新增逻辑维度失败，数据领域code值非法 code:" + dataDomainCode);
            throw new ServiceException(ErrorCodeEnum.GL999999, "新增逻辑维度失败，数据领域code值非法 code:" + dataDomainCode);
        }
        // 逻辑表字段exists验证
//        Long logicTableFieldCode = reqVO.getLogicTableFieldCode();
//        LogicFactTableField logicFactTableField = iLogicFactTableFieldService.queryByCode(logicTableFieldCode);
//        if (logicFactTableField == null) {
//            log.warn("新增逻辑维度失败，逻辑表字段不存在 code:" + logicTableFieldCode);
//            throw new ServiceException(ErrorCodeEnum.GL999999, "新增逻辑维度失败，逻辑表字段不存在 code:" + logicTableFieldCode);
//        }
    }
}
